package fr.inserm.umr915.vcfannotator.annotators;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import fr.inserm.umr915.vcfannotator.AnnotationException;
import org.springframework.core.io.InputStreamSource;

public abstract class AbstractDelimitedAnnotator
	extends AbstractAnnotator
	{
	/* http://www.java2s.com/Tutorial/Java/0417__Spring/Springfactorymethod.htm */
	private Pattern pattern=Pattern.compile("[\t]");
	/** split limit */
	private int splitLimit=-1;
	/** fields */
	private List<Field> fields=new ArrayList<Field>();
	/** inputstream source */
	private InputStreamSource inputStreamSource=null;
	/** current line number */
	private int nLine=0;
	
	public void setPattern(Pattern pattern)
		{
		this.pattern = pattern;
		}
	public Pattern getPattern()
		{
		return pattern;
		}
	
	
	public int getSplitLimit()
		{
		if(this.splitLimit<0)
			{
			if(this.getFields().isEmpty())
				{
				this.splitLimit=0;
				}
			else
				{
				for(Field f: getFields())
					{
					if(f.getColumn()==null) continue;//constant
					this.splitLimit=Math.max(this.splitLimit, f.getColumn()+2);
					}
				if(this.splitLimit<0) this.splitLimit=0;
				}
			}
		return this.splitLimit;
		}
	
	public void setSplitLimit(int splitLimit)
		{
		this.splitLimit = splitLimit;
		}
	
	public String[] split(String line)
		{
		return getPattern().split(line,getSplitLimit());
		}
	
	public boolean ignore(String line)
		{
		return false;
		}
	
	public List<Field> getFields()
		{
		return fields;
		}
	
	public void setFields(List<Field> fields)
		{
		this.fields = fields;
		}
	
	public InputStreamSource getInputStreamSource()
		{
		return inputStreamSource;
		}
	
	public void setInputStreamSource(InputStreamSource inputStreamSource)
		{
		this.inputStreamSource = inputStreamSource;
		}
	public InputStream openStream() throws IOException
		{
		return getInputStreamSource().getInputStream();
		}
	
	public BufferedReader openReader() throws IOException
		{
		LOG.trace("opening reader");
		return new BufferedReader(new InputStreamReader(openStream()));
		}

	public int getLineIndex()
		{
		return this.nLine;
		}
	
	@Override
	public void annotate() throws AnnotationException
		{
		LOG.trace("begin annotate"+getName());
		BufferedReader in=null;
		try {
			this.nLine=0;
			String line;
			
			in=openReader();
			while((line=in.readLine())!=null)
				{
				++this.nLine;
				if(this.nLine%100000==0)
					{
					LOG.trace(line);
					}
				if(ignore(line)) continue;
				annotate(line);
				}
			}
		catch (IOException e)
			{
			throw new AnnotationException(e);
			}
		finally
			{
			this.nLine=0;
			if(in!=null) try { in.close();} catch(IOException err) {} 
			cleanup();
			}
		LOG.trace("end annotate");
		}
	
	public void annotate(String line) throws AnnotationException
		{
		annotate(split(line));
		}
	public abstract void annotate(String tokens[]) throws AnnotationException;
	}
